<template>
  <div class="demo-page">
    <div class="demo-title">通用的数据处理工具，方便用于复杂表单数据提交，反显处理</div>
    <div class="flex-box">
      <el-input v-model="JSON_DATA" rows="20" resize="none" type="textarea" />
      <div class="demo-button">
        <div>
          <el-button type="primary" @click="processData('object', obj, maps)">处理对象</el-button>
        </div>
        <div>
          <el-button @click="processData('array', arr, maps)">处理数组</el-button>
        </div>
      </div>
      <el-input v-model="JSON_RESULT" rows="20" resize="none" type="textarea" />
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      obj: {
        a: '张三',
        b: '18岁',
        sss: ['篮球', '羽毛球', '排球'],
        gg: [{ q: 1, io: [{ y: 's' }] }],
        fuck: function () {}
      },
      arr: [
        1,
        2,
        {
          a: '啊？',
          s: [
            {
              b: [[], [], []]
            }
          ]
        }
      ],
      maps: {
        a: 'name',
        b: 'hello',
        y: '根义哥唧唧裂成拖把'
      },
      result: undefined
    }
  },
  computed: {
    JSON_DATA(ctx) {
      return JSON.stringify(ctx.obj, null, '\t')
    },
    JSON_RESULT(ctx) {
      return JSON.stringify(ctx.result, null, '\t')
    }
  },
  methods: {
    /**
     * 前后端数据字段不一致，最终解决方案，key替换函数
     * */
    /**
     * @param type {String} 传入的data初始数据类型
     * @param data {Array | Object} 传入的data初始数据
     * @param maps {Object} 需要替换的字段枚举，key是替换的目标字段，value想要展示出来的字段，无视数据层级
     * */
    processData(type, data, maps) {
      // 入口拦截，处理对象的话，必须传入对象
      if (type === 'object') {
        if (Object.prototype.toString.call(data) !== '[object Object]') {
          return this.$message.error('传入的初始值，数据类型必须是Object')
        }
      }
      if (type === 'array') {
        if (!Array.isArray(data)) {
          return this.$message.error('传入的初始值，数据类型必须是Array')
        }
      }
      this.result = this.process()[type](data, maps)
    },
    process() {
      const that = this
      return {
        object: that.processObject,
        array: that.processArray
      }
    },
    processObject(data, maps) {
      const that = this
      let target = {}
      Object.keys(data).forEach((key) => {
        if (maps[key]) {
          if (Array.isArray(data[key])) {
            target[maps[key]] = that.processArray(data[key], maps)
          } else if (Object.prototype.toString.call(data[key]) === '[object Object]') {
            target[maps[key]] = that.processObject(data[key], maps)
          } else {
            target[maps[key]] = data[key]
          }
        } else {
          if (Array.isArray(data[key])) {
            target[key] = that.processArray(data[key], maps)
          } else if (Object.prototype.toString.call(data[key]) === '[object Object]') {
            target[key] = that.processObject(data[key], maps)
          } else {
            target[key] = data[key]
          }
        }
      })
      return target
    },
    processArray(data, maps) {
      const that = this
      let target = []
      data.forEach((item) => {
        if (Array.isArray(item)) {
          target.push(that.processArray(item, maps))
        } else if (Object.prototype.toString.call(item) === '[object Object]') {
          target.push(that.processObject(item, maps))
        } else {
          target.push(item)
        }
      })
      return target
    }
  }
}
</script>

<style scoped>
.demo-page {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 14px;
}
.demo-title {
  margin-bottom: 12px;
}
.demo-button {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: 0 12px;
}
.demo-button > div:first-child {
  margin-bottom: 12px;
}
.flex-box {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}
</style>
